package cn.zhqr.lib.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.log4j.Logger;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

/**
 * Created by charles on 2018/12/7.
 */
public class ImageUtil {
    private static final Logger log = Logger.getLogger(ImageUtil.class);

    public static final int BLACK = 0xFF000000;
    public static final int WHITE = 0xFFFFFFFF;
    public enum Align {
        Left, Right, Center;
    }
    public enum VerticalAlign {
        Top, Bottom, Medium;
    }

    public static BufferedImage readClassPathFile(String filePath){
        return readFile(ImageUtil.class.getClassLoader().getResource(filePath).getFile());
    }

    public static BufferedImage readFile(String filePath){
        return readFile(new File(filePath));
    }

    public static BufferedImage readFile(File file) {
        try {
            return ImageIO.read(file);
        } catch (Exception e) {
            log.error(e);
        }
        return null;
    }
    public static boolean saveImage(RenderedImage bf, String formatName, File destFile) throws IOException {
        return ImageIO.write(bf, formatName, destFile);
    }

    public static boolean saveImage(RenderedImage bf, String destFilePath) throws IOException {
        return saveImage(bf,new File(destFilePath));
    }
    public static boolean saveImage(RenderedImage bf, File destFile) throws IOException {
        if (bf == null || destFile == null) {
            return false;
        }
        String formatName = "jpg";
        int pos;
        if ((pos = destFile.getName().lastIndexOf('.')) > 0) {
            String suffixName = destFile.getName().substring(pos + 1).toLowerCase();
            String[] formatNames = ImageIO.getWriterFormatNames();
            for (int i = 0; i < formatNames.length; i++) {
                if (suffixName.equalsIgnoreCase(formatNames[i])) {
                    formatName = formatNames[i];
                    break;
                }
            }
        }
        return saveImage(bf, formatName, destFile);
    }

    public static BufferedImage createQrcode(String content,int width, int height){
        return createQrcode(content, width, height,BLACK, WHITE);
    }

    public static BufferedImage createQrcode(String content,int width, int height, int foreColor, int backColor){
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 文字编码。
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.MARGIN,0);


        BufferedImage image = null;
        try {
            com.google.zxing.qrcode.QRCodeWriter qrCodeWriter = new com.google.zxing.qrcode.QRCodeWriter();
            BitMatrix matrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            image = ImageUtil.toBufferedImage(matrix, foreColor, backColor);
        } catch (Exception e) {
            log.error("createQrcode(String, BarcodeFormat, Hashtable, int, int, int, int)", e);
        }

        return image;
    }

    public static BufferedImage createQrcode(String content, BarcodeFormat format, int width, int height, int foreColor, int backColor)
            throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 文字编码。
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

        BufferedImage image = null;
        if (!((format == BarcodeFormat.QR_CODE))) {
            throw new IllegalArgumentException("Not a available 1D format " + format);
        }
        try {
            com.google.zxing.qrcode.QRCodeWriter qrCodeWriter = new com.google.zxing.qrcode.QRCodeWriter();
            @SuppressWarnings("unchecked")
            BitMatrix matrix = qrCodeWriter.encode(content, format, width, height, hints);
            image = ImageUtil.toBufferedImage(matrix, foreColor, backColor);
        } catch (Exception e) {
            log.error("createQrcode(String, BarcodeFormat, Hashtable, int, int, int, int)", e);
        }

        return image;
    }

    public static BufferedImage toBufferedImage(BitMatrix matrix, int foreColor, int backColor) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? foreColor : backColor);
            }
        }
        return image;
    }

    public static void graphicsDrawString(Graphics g,String str, int x, int y, int textSpace,Align align,VerticalAlign verticalAlign) {
        String tempStr = new String();
        int orgStringWight = g.getFontMetrics().stringWidth(str);
        int orgStringLength = str.length();
        int tempx;
        int tempy = y;

//        FontMetrics fontMetrics = FontDesignMetrics.getMetrics(g.getFont());
//        int str_width  = fontMetrics.stringWidth(str)+(str.length()-1)*textSpace;
//        int str_height  = fontMetrics.getAscent()-fontMetrics.getDescent();

        //找不到类sun.font.FontDesignMetrics，以此方式代替
        FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true);
        Rectangle rec = g.getFont().getStringBounds("a", frc).getBounds();

        int str_height = (int) rec.getHeight();
        int str_width = (int) rec.getWidth();

        if(align == Align.Left){
            tempx = x;
        }else if(align == Align.Right){
            tempx = x - str_width;
        }else{
            tempx = x - str_width/2;
        }

        if(verticalAlign == VerticalAlign.Top){
            tempy = y + str_height;
        }else if(verticalAlign == VerticalAlign.Bottom){
            tempy = y;
        }else{
            tempy = y + str_height/2;
        }

        while (str.length() > 0) {
            tempStr = str.substring(0, 1);
            str = str.substring(1, str.length());
            g.drawString(tempStr, tempx, tempy);
            tempx = (int) (tempx + (double) orgStringWight / (double) orgStringLength + textSpace);
        }
    }
}
